package org.dding.msc.service;

/**
 * A listener for service lifecycle events. The associated controller will not leave its current state until
 * all listeners finish running.
 *
 * @param <S> the service type
 *
 */
public interface ServiceListener<S> {

    /**
     * The listener has been added to a controller.
     *
     * @param controller the controller that this listener was added to
     */
    void listenerAdded(ServiceController<? extends S> controller);

    /**
     * The service has transitioned to a new sub-state.
     *
     * @param controller the controller
     * @param transition the transition that occurred
     */
    void transition(ServiceController<? extends S> controller, ServiceController.Transition transition);


    /**
     * The service is going to be removed.  Called when the service mode is changed to {@code REMOVE}.
     *
     * @param controller the controller
     */
    void serviceRemoveRequested(ServiceController<? extends S> controller);

    void serviceUnavailable(ServiceController<? extends S> controller);

    void serviceAvailable(ServiceController<? extends S> controller);

    /**
     * A transitive dependency of the service is uninstalled or administratively {@link ServiceController.Mode#NEVER
     * disabled}.
     * <p> Transitive dependencies that are subsequently unavailable do not result in new {@code
     * transitiveDependencyUnavailable} notifications. A new call to this method will only be made to notify newly found
     * unavailable dependencies if the previously unavailable dependencies have all become {@link
     * #transitiveServiceAvailable(ServiceController) available}.
     *
     * @param controller the controller
     */
    void transitiveServiceUnavailable(ServiceController<? extends S> controller);

    /**
     * All {@link #transitiveServiceUnavailable(ServiceController) unavailable} transitive dependencies of the
     * service are now available (installed and not administratively {@link ServiceController.Mode#NEVER disabled}).
     * <br>This method will be invoked only after {@link #transitiveServiceUnavailable(ServiceController)} is called.
     *
     * @param controller the controller
     */
    void transitiveServiceAvailable(ServiceController<? extends S> controller);

    /**
     * The inheritance type for a listener.
     */
    enum Inheritance {
        /**
         * This listener is never inherited.
         */
        NONE,
        /**
         * This listener is inherited only to one level.
         */
        ONCE,
        /**
         * This listener is inherited to all levels.
         */
        ALL,
        ;
    }
}